function M = visterm_encode(X, C, distfun)
%VISTERM_ENCODE Encoding an image of features by visual term matching
%
%   M = VISTERM_ENCODE(X, C);
%   
%       Visual term encoding means to assign to each local descriptor
%       with an integer label. 
%
%       In this function, with a dictionary of visual terms, each local
%       descriptor is converted to the index of the visual term that is
%       most close to it (in terms of Euclidean distance)
%
%       Suppose the image size is [h, w], the descriptor has dimension d,
%       and the dictionary size is m.
%
%       Inputs
%       ------
%       - X:        The map of descriptors [size: d x h x w].
%       - C:        The visual term dictionary [size: d x m].
%
%       Outputs
%       -------
%       - M:        The label map [size h x w]. 
%                   The value of each element in M is an integer between
%                   1 and m.
%
%
%   M = VISTERM_ENCODE(X, C, distfun);
%
%       Uses user-supplied function for evaluating distances between 
%       visual terms and descriptors.
%
%           D = distfun(C, Y);
%
%       This statement should yield a matrix D of size m x n, when 
%       C is a matrix of d x m, and Y is a matrix of size d x n. 
%

% Created by Dahua Lin, on Mar 8, 2012
%

%% verify input arguments

if ~(isfloat(X) && isreal(X) && ndims(X) <= 3)
    error('visterm_encode:invalidarg', ...
        'X should be a real array with ndims(X) <= 3.');
end
[d, h, w] = size(X);

if ~(isfloat(C) && isreal(C) && ndims(C) == 2 && size(C, 1) == d)
    error('visterm_encode:invalidarg', ...
        'C should be a real matrix with size(C,1) == d.');
end

if nargin < 3
    distfun = @pwsqL2dist;
else
    if ~isa(distfun, 'function_handle')
        error('visterm_encode:invalidarg', ...
            'distfun should be a function handle.');
    end
end
    

%% main

if w > 1
    X = reshape(X, [h * w, 1]);
end

D = distfun(C, X);
[~, M] = min(D, [], 1);
M = reshape(M, [h w]);


